package org.smartjava.core.juc.atomic;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import static java.util.concurrent.ThreadLocalRandom.current;

/**
 * @author wyaoyao
 * @date 2021/4/19 17:19
 */
public class A {


    /**
     * 定义AtomicReference并且初始值为DebitCard("zhangsan", 0)
     */
    private static AtomicReference<DebitCard> debitCardRef
            = new AtomicReference<>(new DebitCard("zhangsan", 0));
    private static DebitCard debitCard = new DebitCard("zhangsan2", 0);

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch2 = new CountDownLatch(200);
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                debitCard = new DebitCard(debitCard.getAccount(), debitCard.getAmount() + 10);
                countDownLatch2.countDown();
            }, "simple+i").start();

        }
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                debitCard = new DebitCard(debitCard.getAccount(), debitCard.getAmount() - 10);
                countDownLatch2.countDown();
            }, "simple+i").start();
        }


        CountDownLatch countDownLatch = new CountDownLatch(2000);
        for (int i = 0; i < 1000; i++) {
            new Thread("T-add-" + i) {
                @Override
                public void run() {
                    DebitCard debitCard = debitCardRef.updateAndGet(debitCard1 -> new DebitCard(debitCard1.getAccount(), debitCard1.getAmount() + 10));
                    System.out.println(Thread.currentThread().getName() + ":" + debitCard);

                    try {
                        TimeUnit.MILLISECONDS.sleep(current().nextInt(20));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    countDownLatch.countDown();
                }
            }.start();
        }
        for (int i = 0; i < 1000; i++) {
            new Thread("T-minus-" + i) {
                @Override
                public void run() {
                    DebitCard debitCard = debitCardRef.updateAndGet(debitCard1 -> new DebitCard(debitCard1.getAccount(), debitCard1.getAmount() - 10));
                    System.out.println(Thread.currentThread().getName() + ":" + debitCard);

                    try {
                        TimeUnit.MILLISECONDS.sleep(current().nextInt(20));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    countDownLatch.countDown();
                }
            }.start();
        }
        countDownLatch.await();
        countDownLatch2.await();
        System.out.println(debitCard);
        System.out.println(debitCardRef.get());
    }
}


class DebitCard {

    /**
     * 账户名名
     */
    private final String account;

    /**
     * 账户金额
     */
    private final int amount;

    public DebitCard(String account, int amount) {
        this.account = account;
        this.amount = amount;
    }

    public String getAccount() {
        return account;
    }

    public int getAmount() {
        return amount;
    }

    @Override
    public String toString() {
        return "DebitCard{" +
                "account='" + account + '\'' +
                ", amount=" + amount +
                '}';
    }
}
